package main

import (
	mqtt "github.com/eclipse/paho.mqtt.golang"
	"github.com/flipped-aurora/gin-vue-admin/server/core"
	"github.com/flipped-aurora/gin-vue-admin/server/global"
	"github.com/flipped-aurora/gin-vue-admin/server/initialize"
	"github.com/flipped-aurora/gin-vue-admin/server/service/system"
	_ "go.uber.org/automaxprocs"
	"go.uber.org/zap"
	"os"
	"os/signal"
	"syscall"
)

//go:generate go env -w GO111MODULE=on
//go:generate go env -w GOPROXY=https://goproxy.cn,direct
//go:generate go mod tidy
//go:generate go mod download

// 这部分 @Tag 设置用于排序, 需要排序的接口请按照下面的格式添加
// swag init 对 @Tag 只会从入口文件解析, 默认 main.go
// 也可通过 --generalInfo flag 指定其他文件
// @Tag.Name        Base
// @Tag.Name        SysUser
// @Tag.Description 用户

// @title                       Gin-Vue-Admin Swagger API接口文档
// @version                     v2.8.2
// @description                 使用gin+vue进行极速开发的全栈开发基础平台
// @securityDefinitions.apikey  ApiKeyAuth
// @in                          header
// @name                        x-token
// @BasePath                    /
func main() {
	// 初始化系统
	initializeSystem()
	// 初始化MQTT客户端并订阅主题
	initMQTT()
	// 运行服务器
	core.RunServer()

}

// initializeSystem 初始化系统所有组件
// 提取为单独函数以便于系统重载时调用
func initializeSystem() {
	global.GVA_VP = core.Viper() // 初始化Viper
	initialize.OtherInit()
	global.GVA_LOG = core.Zap() // 初始化zap日志库
	zap.ReplaceGlobals(global.GVA_LOG)
	global.GVA_DB = initialize.Gorm() // gorm连接数据库
	initialize.Timer()
	initialize.DBList()
	initialize.SetupHandlers() // 注册全局函数
	if global.GVA_DB != nil {
		initialize.RegisterTables() // 初始化表
	}
	global.InitRedis()
}
func initMQTT() {
	// 从配置中获取MQTT相关参数
	mqttBroker := global.GVA_VP.GetString("mqtt.broker")
	mqttClientID := global.GVA_VP.GetString("mqtt.client_id")
	mqttUsername := global.GVA_VP.GetString("mqtt.username")
	mqttPassword := global.GVA_VP.GetString("mqtt.password")
	mqttTopic := global.GVA_VP.GetString("mqtt.topic")

	// 配置MQTT客户端选项
	opts := mqtt.NewClientOptions()
	opts.AddBroker(mqttBroker)
	opts.SetClientID(mqttClientID)
	if mqttUsername != "" && mqttPassword != "" {
		opts.SetUsername(mqttUsername)
		opts.SetPassword(mqttPassword)
	}

	// 设置连接回调
	opts.OnConnect = func(client mqtt.Client) {
		global.GVA_LOG.Info("MQTT客户端连接成功")
		// 连接成功后立即订阅主题
		if token := client.Subscribe(mqttTopic, 0, mqttMessageHandler); token.Wait() && token.Error() != nil {
			global.GVA_LOG.Error("MQTT订阅主题失败", zap.Error(token.Error()))
		} else {
			global.GVA_LOG.Info("已订阅MQTT主题", zap.String("topic", mqttTopic))
		}
	}

	// 设置连接丢失回调
	opts.OnConnectionLost = func(client mqtt.Client, err error) {
		global.GVA_LOG.Error("MQTT连接丢失", zap.Error(err))
	}

	// 创建MQTT客户端并连接
	client := mqtt.NewClient(opts)
	if token := client.Connect(); token.Wait() && token.Error() != nil {
		global.GVA_LOG.Fatal("MQTT客户端连接失败", zap.Error(token.Error()))
	}

	// 保存MQTT客户端到全局变量，方便其他包使用
	global.GVA_MQTT_CLIENT = client

	// 初始化MQTT消息管理器
	global.GVA_MQTT_MESSAGE_MANAGER = interface{}(system.NewMQTTMessageManager(client))
	global.GVA_LOG.Info("MQTT消息管理器初始化成功")

	// 优雅退出时断开MQTT连接
	go handleGracefulShutdown(client)
}

// mqttMessageHandler MQTT消息处理函数
var mqttMessageHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) {
	global.GVA_LOG.Info("接收到MQTT消息",
		zap.String("topic", msg.Topic()),
		zap.String("payload", string(msg.Payload())))

	// 创建设备服务实例处理消息
	deviceService := system.NewDeviceService(global.GVA_DB, client)

	// 处理设备状态更新消息（假设消息格式为JSON）
	if err := deviceService.HandleMQTTDeviceStatus(msg.Topic(), msg.Payload()); err != nil {
		global.GVA_LOG.Error("处理MQTT消息失败",
			zap.String("topic", msg.Topic()),
			zap.Error(err))
	}
}

// handleGracefulShutdown 处理服务优雅退出
func handleGracefulShutdown(client mqtt.Client) {
	quit := make(chan os.Signal, 1)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit

	global.GVA_LOG.Info("接收到退出信号，正在关闭MQTT连接...")
	client.Disconnect(250)
	global.GVA_LOG.Info("MQTT连接已关闭")
}
